﻿using Gargoyle.Roton;
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;

namespace Gargoyle.ZZT
{
    public class State
    {
        virtual public int ActIndex { get; set; }
        virtual public bool AlertAmmo { get; set; }
        virtual public bool AlertCantShoot { get; set; }
        virtual public bool AlertDark { get; set; }
        virtual public bool AlertEnergy { get; set; }
        virtual public bool AlertFake { get; set; }
        virtual public bool AlertForest { get; set; }
        virtual public bool AlertGem { get; set; }
        virtual public bool AlertNoAmmo { get; set; }
        virtual public bool AlertNotDark { get; set; }
        virtual public bool AlertNoTorch { get; set; }
        virtual public bool AlertTorch { get; set; }
        virtual public bool BreakGameLoop { get; set; }
        virtual public bool EditorMode { get; set; }
        public bool EnteringBoard { get; set; }
        virtual public int ForestMusicIndex { get; set; }
        virtual public bool GameOver { get; set; }
        public bool InitGame { get; set; }
        public bool InitGameLoop { get; set; }
        virtual public bool KeyArrow { get; set; }
        public Keys KeyPressed { get; set; }
        virtual public bool KeyShift { get; set; }
        public Vector KeyLastVector { get; set; }
        public Vector KeyVector;
        virtual public byte OOPByte { get; set; }
        virtual public int OOPNumber { get; set; }
        virtual public ByteString OOPWord { get; set; }
        virtual public bool Paused { get; set; }
        public bool PausedBlink { get; set; }
        public Element PlayerElement { get; set; }
        virtual public bool Quiet { get; set; }
        virtual public bool QuitZZT { get; set; }
        public Queue<byte> SoundData { get; set; }
        virtual public bool SoundPlaying { get; set; }
        virtual public int SoundPriority { get; set; }
        virtual public byte SoundTicks { get; set; }
        virtual public int Speed { get; set; }
        virtual public Int16 StartBoard { get; set; }
        public int Tick { get; set; }
        public int TimeOnBoard { get; set; }
        public bool TitleScreen { get; set; }
        virtual public int WaitTime { get; set; }

        public State()
        {
            SoundData = new Queue<byte>();
        }

        public void Reset()
        {
            ActIndex = 0;
            AlertAmmo = true;
            AlertCantShoot = true;
            AlertDark = true;
            AlertEnergy = true;
            AlertFake = true;
            AlertForest = true;
            AlertGem = true;
            AlertNoAmmo = true;
            AlertNotDark = true;
            AlertNoTorch = true;
            AlertTorch = true;
            BreakGameLoop = false;
            EditorMode = false;
            EnteringBoard = false;
            ForestMusicIndex = 0;
            GameOver = false;
            InitGame = true;
            InitGameLoop = false;
            KeyArrow = false;
            KeyPressed = Keys.None;
            KeyShift = false;
            KeyLastVector = new Vector(0, 0);
            KeyVector = new Vector(0, 0);
            OOPByte = 0;
            OOPNumber = 0;
            OOPWord = new byte[0];
            Paused = false;
            PausedBlink = false;
            PlayerElement = null;
            Quiet = false;
            QuitZZT = false;
            SoundPlaying = false;
            SoundPriority = 0;
            SoundTicks = 0;
            Speed = 4;
            StartBoard = 0;
            Tick = 0;
            TimeOnBoard = 0;
            TitleScreen = false;
            WaitTime = 0;
        }
    }

    abstract public class MemoryBlockState : State
    {
        protected Pointer ptrAboutShown;
        protected Pointer ptrActIndex;
        protected Pointer ptrAlertAmmo;
        protected Pointer ptrAlertDark;
        protected Pointer ptrAlertEnergy;
        protected Pointer ptrAlertFake;
        protected Pointer ptrAlertForest;
        protected Pointer ptrAlertGem;
        protected Pointer ptrAlertNoAmmo;
        protected Pointer ptrAlertNoShoot;
        protected Pointer ptrAlertNotDark;
        protected Pointer ptrAlertNoTorch;
        protected Pointer ptrAlertTorch;
        protected Pointer ptrBoardCount;
        protected Pointer ptrBorderTile;
        protected Pointer ptrBreakGameLoop;
        protected Pointer ptrCancelScroll;
        protected Pointer ptrDefaultBoardName;
        protected Pointer ptrDefaultSaveName;
        protected Pointer ptrDefaultWorldName;
        protected Pointer ptrEdgeTile;
        protected Pointer ptrEditorMode;
        protected Pointer ptrForestSoundIndex;
        protected Pointer ptrGameCycle;
        protected Pointer ptrGameOver;
        protected Pointer ptrGamePaused;
        protected Pointer ptrGameQuiet;
        protected Pointer ptrGameSpeed;
        protected Pointer ptrGameWaitTime;
        protected Pointer ptrInit;
        protected Pointer ptrKeyArrow;
        protected Pointer ptrKeyPressed;
        protected Pointer ptrKeyShift;
        protected Pointer ptrKeyVector;
        protected Pointer ptrLineChars;
        protected Pointer ptrMessage;
        protected Pointer ptrOopByte;
        protected Pointer ptrOopNumber;
        protected Pointer ptrOopWord;
        protected Pointer ptrPlayerElement;
        protected Pointer ptrQuitZZT;
        protected Pointer ptrSoundBuffer;
        protected Pointer ptrSoundPlaying;
        protected Pointer ptrSoundPriority;
        protected Pointer ptrSoundTicks;
        protected Pointer ptrStarChars;
        protected Pointer ptrStartBoard;
        protected Pointer ptrThingCount;
        protected Pointer ptrTransporterH;
        protected Pointer ptrTransporterV;
        protected Pointer ptrVector4;
        protected Pointer ptrVector8;
        protected Pointer ptrVisibleTileCount;
        protected Pointer ptrWebChars;
        protected Pointer ptrWorldFileName;
        protected Pointer ptrWorldLoaded;

        public override int ActIndex
        {
            get
            {
                return ptrActIndex.Int16;
            }
            set
            {
                ptrActIndex.Int16 = (Int16)value;
            }
        }

        public override bool AlertAmmo
        {
            get
            {
                return ptrAlertAmmo.Bool;
            }
            set
            {
                ptrAlertAmmo.Bool = value;
            }
        }

        public override bool AlertCantShoot
        {
            get
            {
                return ptrAlertNoShoot.Bool;
            }
            set
            {
                ptrAlertNoShoot.Bool = value;
            }
        }

        public override bool AlertDark
        {
            get
            {
                return ptrAlertDark.Bool;
            }
            set
            {
                ptrAlertDark.Bool = value;
            }
        }

        public override bool AlertEnergy
        {
            get
            {
                return ptrAlertEnergy.Bool;
            }
            set
            {
                ptrAlertEnergy.Bool = value;
            }
        }

        public override bool AlertFake
        {
            get
            {
                return ptrAlertFake.Bool;
            }
            set
            {
                ptrAlertFake.Bool = value;
            }
        }

        public override bool AlertForest
        {
            get
            {
                return ptrAlertForest.Bool;
            }
            set
            {
                ptrAlertForest.Bool = value;
            }
        }

        public override bool AlertGem
        {
            get
            {
                return ptrAlertGem.Bool;
            }
            set
            {
                ptrAlertGem.Bool = value;
            }
        }

        public override bool AlertNoAmmo
        {
            get
            {
                return ptrAlertNoAmmo.Bool;
            }
            set
            {
                ptrAlertNoAmmo.Bool = value;
            }
        }

        public override bool AlertNotDark
        {
            get
            {
                return ptrAlertNotDark.Bool;
            }
            set
            {
                ptrAlertNotDark.Bool = value;
            }
        }

        public override bool AlertNoTorch
        {
            get
            {
                return ptrAlertNoTorch.Bool;
            }
            set
            {
                ptrAlertNoTorch.Bool = value;
            }
        }

        public override bool AlertTorch
        {
            get
            {
                return ptrAlertTorch.Bool;
            }
            set
            {
                ptrAlertTorch.Bool = value;
            }
        }

        public override bool BreakGameLoop
        {
            get
            {
                return ptrBreakGameLoop.Bool;
            }
            set
            {
                ptrBreakGameLoop.Bool = value;
            }
        }

        public override bool EditorMode
        {
            get
            {
                return ptrEditorMode.Bool;
            }
            set
            {
                ptrEditorMode.Bool = value;
            }
        }

        public override int ForestMusicIndex
        {
            get
            {
                return ptrForestSoundIndex.Int16;
            }
            set
            {
                ptrForestSoundIndex.Int16 = (Int16)value;
            }
        }

        public override bool GameOver
        {
            get
            {
                return ptrGameOver.Bool;
            }
            set
            {
                ptrGameOver.Bool = value;
            }
        }

        public override bool KeyArrow
        {
            get
            {
                return ptrKeyArrow.Bool;
            }
            set
            {
                ptrKeyArrow.Bool = value;
            }
        }

        public override bool KeyShift
        {
            get
            {
                return ptrKeyShift.Bool;
            }
            set
            {
                ptrKeyShift.Bool = value;
            }
        }

        public override byte OOPByte
        {
            get
            {
                return ptrOopByte.Byte;
            }
            set
            {
                ptrOopByte.Byte = value;
            }
        }

        public override int OOPNumber
        {
            get
            {
                return ptrOopNumber.Int16;
            }
            set
            {
                ptrOopNumber.Int16 = (Int16)value;
            }
        }

        public override ByteString OOPWord
        {
            get
            {
                return ptrOopWord.String;
            }
            set
            {
                ptrOopWord.String = value;
            }
        }

        public override bool Paused
        {
            get
            {
                return ptrGamePaused.Bool;
            }
            set
            {
                ptrGamePaused.Bool = value;
            }
        }

        public override bool Quiet
        {
            get
            {
                return ptrGameQuiet.Bool;
            }
            set
            {
                ptrGameQuiet.Bool = value;
            }
        }

        public override bool QuitZZT
        {
            get
            {
                return ptrQuitZZT.Bool;
            }
            set
            {
                ptrQuitZZT.Bool = value;
            }
        }

        public override bool SoundPlaying
        {
            get
            {
                return ptrSoundPlaying.Bool;
            }
            set
            {
                ptrSoundPlaying.Bool = value;
            }
        }

        public override int SoundPriority
        {
            get
            {
                return ptrSoundPriority.Int16;
            }
            set
            {
                ptrSoundPriority.Int16 = (Int16)value;
            }
        }

        public override byte SoundTicks
        {
            get
            {
                return ptrSoundTicks.Byte;
            }
            set
            {
                ptrSoundTicks.Byte = value;
            }
        }

        public override int Speed
        {
            get
            {
                return ptrGameSpeed.Byte;
            }
            set
            {
                ptrGameSpeed.Byte = (byte)value;
            }
        }

        public override short StartBoard
        {
            get
            {
                return ptrStartBoard.Int16;
            }
            set
            {
                ptrStartBoard.Int16 = value;
            }
        }

        public override int WaitTime
        {
            get
            {
                return ptrGameWaitTime.Int16;
            }
            set
            {
                ptrGameWaitTime.Int16 = (Int16)value;
            }
        }
    }

    sealed public class ZZTState : MemoryBlockState
    {
        Memory mem;

        public ZZTState(Memory mem)
            : base()
        {
            this.mem = mem;

            ptrAboutShown = mem[0x7A60];
            ptrActIndex = mem[0x7406];
            ptrAlertAmmo = mem[0x4AAB];
            ptrAlertDark = mem[0x4AB1];
            ptrAlertEnergy = mem[0x4AB5];
            ptrAlertFake = mem[0x4AB3];
            ptrAlertForest = mem[0x4AB2];
            ptrAlertGem = mem[0x4AB4];
            ptrAlertNoAmmo = mem[0x4AAC];
            ptrAlertNoShoot = mem[0x4AAD];
            ptrAlertNotDark = mem[0x4AB0];
            ptrAlertNoTorch = mem[0x4AAF];
            ptrAlertTorch = mem[0x4AAE];
            ptrBoardCount = mem[0x45BE];
            ptrBorderTile = mem[0x0072];
            ptrBreakGameLoop = mem[0x4AC6];
            ptrCancelScroll = mem[0x7B66];
            ptrDefaultBoardName = mem[0x241E];
            ptrDefaultSaveName = mem[0x23EA];
            ptrDefaultWorldName = mem[0x2452];
            ptrEdgeTile = mem[0x0074];
            ptrEditorMode = mem[0x740C];
            ptrForestSoundIndex = null;
            ptrGameCycle = mem[0x7404];
            ptrGameOver = mem[0x7C8D];
            ptrGamePaused = mem[0x7408];
            ptrGameQuiet = mem[0x7C8C];
            ptrGameSpeed = mem[0x4ACE];
            ptrGameWaitTime = mem[0x7402];
            ptrInit = mem[0x7B60];
            ptrKeyArrow = mem[0x7C7E];
            ptrKeyPressed = mem[0x7C70];
            ptrKeyShift = mem[0x7C6C];
            ptrKeyVector = mem[0x7C68];
            ptrLineChars = mem[0x0098];
            ptrMessage = mem[0x456E];
            ptrOopByte = mem[0x740E];
            ptrOopNumber = mem[0x7426];
            ptrOopWord = mem[0x7410];
            ptrPlayerElement = mem[0x4AC8];
            ptrQuitZZT = mem[0x4AC5];
            ptrSoundBuffer = mem[0x7E90];
            ptrSoundPlaying = mem[0x7F9A];
            ptrSoundPriority = mem[0x7C8E];
            ptrSoundTicks = mem[0x7E8F];
            ptrStarChars = mem[0x0336];
            ptrStartBoard = mem[0x4ACA];
            ptrThingCount = mem[0x31CD];
            ptrTransporterH = mem[0x0236];
            ptrTransporterV = mem[0x0136];
            ptrVector4 = mem[0x0062];
            ptrVector8 = mem[0x0042];
            ptrVisibleTileCount = mem[0x4ACC];
            ptrWebChars = null;
            ptrWorldFileName = mem[0x23B6];
            ptrWorldLoaded = mem[0x7428];

            Reset();
        }

        public override int ForestMusicIndex
        {
            get
            {
                return 0;
            }
            set
            {
            }
        }

        public override int Speed
        {
            get
            {
                return base.Speed;
            }
            set
            {
                base.Speed = value;
            }
        }
    }

    sealed public class SuperZZTState : MemoryBlockState
    {
        Memory mem;

        public SuperZZTState(Memory mem)
            : base()
        {
            this.mem = mem;

            ptrActIndex = mem[0xB95A];
            ptrAlertAmmo = mem[0x7C0B];
            ptrAlertEnergy = mem[0x7C11];
            ptrAlertFake = mem[0x7C0F];
            ptrAlertForest = mem[0x7C0E];
            ptrAlertGem = mem[0x7C10];
            ptrAlertNoAmmo = mem[0x7C0C];
            ptrAlertNoShoot = mem[0x7C0D];
            ptrBoardCount = mem[0x7784];
            ptrBreakGameLoop = mem[0x7C9E];
            ptrDefaultBoardName = mem[0x2B32];
            ptrDefaultSaveName = mem[0x2AF4];
            ptrDefaultWorldName = mem[0x2B70];
            ptrEdgeTile = mem[0x2260];
            ptrEditorMode = mem[0xB960];
            ptrForestSoundIndex = mem[0x2334];
            ptrGameCycle = mem[0xB958];
            ptrGameOver = mem[0xCD9B];
            ptrGamePaused = mem[0xB95C];
            ptrGameQuiet = mem[0xCD9A];
            ptrGameSpeed = mem[0x7CA4];
            ptrGameWaitTime = mem[0xB956];
            ptrKeyArrow = mem[0xCC84];
            ptrKeyPressed = mem[0xCC76];
            ptrKeyShift = mem[0xCC72];
            ptrKeyVector = mem[0xCC6E];
            ptrLineChars = mem[0x22BA];
            ptrMessage = mem[0x7C22];
            ptrOopByte = mem[0xB962];
            ptrOopNumber = mem[0xB97A];
            ptrOopWord = mem[0xB964];
            ptrPlayerElement = mem[0x7CA0];
            ptrQuitZZT = mem[0x7C9D];
            ptrSoundBuffer = mem[0xCF9E];
            ptrSoundPlaying = mem[0xD0A8];
            ptrSoundPriority = mem[0xCD9C];
            ptrSoundTicks = mem[0xCF9D];
            ptrStarChars = mem[0x2064];
            ptrStartBoard = mem[0x7CA2];
            ptrThingCount = mem[0x6AB3];
            ptrTransporterH = mem[0x1F64];
            ptrTransporterV = mem[0x1E64];
            ptrVector4 = mem[0x2250];
            ptrVector8 = mem[0x2230];
            ptrWebChars = mem[0x227C];
            ptrWorldFileName = mem[0x2AB6];
            ptrWorldLoaded = mem[0xB97C];

            Reset();
        }

        public override bool AlertDark
        {
            get
            {
                return false;
            }
            set
            {
            }
        }

        public override bool AlertNotDark
        {
            get
            {
                return false;
            }
            set
            {
            }
        }

        public override bool AlertNoTorch
        {
            get
            {
                return false;
            }
            set
            {
            }
        }

        public override bool AlertTorch
        {
            get
            {
                return false;
            }
            set
            {
            }
        }
    }
}
